package cn.lcfms.cms;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.ListIterator;
import java.util.Stack;
import org.apache.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import cn.lcfms.bin.Broadcast;
import cn.lcfms.bin.Userinfo;
import net.sf.json.JSONObject;

public class CollctBase{
	private static Logger logger = Logger.getLogger(Collect.class); 
	private static Stack<String> stack=new Stack<>();
	private static HashSet<String> used=new HashSet<>();
	private static HashMap<String, String> aimg=new HashMap<>();
	protected static String getStackUrl() {
		if(stack.size()==0) {
			return null;
		}
		String pop = stack.pop();
		if(used.contains(pop)) {
			return getStackUrl();
		}
		return pop;
	}
	
	protected static String getAimg() {	
		String key=Collect.getColl().getNowUrl();
		if(aimg.containsKey(key)) {
			return aimg.get(key);
		}
		return null;
	}
	
	protected static void removeAimg() {	
		String key=Collect.getColl().getNowUrl();
		if(aimg.containsKey(key)) {
			aimg.remove(key);
		}
	}
	
	protected static synchronized void update(Collect coll){
		int type = coll.getBean().getType();
		if(type==1 && stack.size()==0) {
			String msg = getPageA(coll.getBean().getUrl(),coll.getBean().getCookie(),coll.getBean().getCharset(),coll.getBean().getPreg());
			if(!msg.equals("")) {
				coll.setSuccess(false);
				coll.setMsg(msg);
			}
		}
		if(type==2 && stack.size()==0) {
			for(int i=coll.getBean().getBegin();i<=coll.getBean().getEnd();i++) {
				String url=coll.getBean().getPreg().replace("{数字}", String.valueOf(i));
				stack.push(url);
			}		
		}
		if(type==3 && stack.size()==0) {
			String msg = getPageA(coll.getBean().getUrl(),coll.getBean().getCookie(),coll.getBean().getCharset(),coll.getBean().getPreg());
			if(!msg.equals("")) {
				coll.setSuccess(false);
				coll.setMsg(msg);
			}
		}
		while(coll.loopCollct()) {
			boolean success=coll.isSuccess();
			if(success) {
				success(coll.getMsg());
			}else {
				error(coll.getMsg());
			}	
			System.out.println("未访问："+stack.size()+"，已经访问："+used.size());
			System.out.println("");
			if(stack.size()==0) {				
				coll.stop();
				layer("采集已完成，共采集数据"+coll.getNum()+"条");
			}
		}
	}
	
	protected static void clearUrl() {
		stack.clear();
		used.clear();
		aimg.clear();
	}
	
	protected static byte[] browser(String urlpath,String cookie) throws IOException {
		used.add(urlpath);
		URL url = new URL(urlpath);
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setConnectTimeout(5000);
		conn.setRequestMethod("GET");
		conn.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36");
		if(cookie!=null && !"".equals(cookie)) {
			conn.setRequestProperty("Cookie", cookie.trim());
		}
		byte[] b;
		if (conn.getResponseCode() == 200) {
			InputStream inputStream = conn.getInputStream();
			BufferedInputStream buffer = new BufferedInputStream(inputStream);
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			byte[] bs = new byte[1024];
			int len = -1;
			while ((len = buffer.read(bs)) != -1) {
				bos.write(bs, 0, len);
			}
			b = bos.toByteArray();
			bos.close();
			buffer.close();
			inputStream.close();
			return b;			
		}
		throw new IOException();
	}	
	
	protected static String getPageA(String url,String cookie,String charset,String preg) {
		String content;
		String host;
		String path;
		try {
			logger.info("获取指定页面："+url);
			byte[] b = browser(url,cookie);
			content=new String(b,charset);
			if(content==null || content.equals("")) {
				return "指定页面返回的内容为空";
			}
			URL _url=new URL(url);
			path=_url.getProtocol()+"://"+_url.getHost()+_url.getFile();
			path=path.substring(0, path.lastIndexOf("/"))+"/";
			host=_url.getProtocol()+"://"+_url.getHost()+"/";
		} catch (IOException e) {
			return "IO异常，连接请求失败";
		}			
		Document doc = Jsoup.parse(content);
		Elements a = doc.select("a[href]");
		ListIterator<Element> iterator = a.listIterator();
		int i=0;
		while (iterator.hasNext()) {
			Element next = iterator.next();
			String attr = next.attr("href");				
			if(attr.matches(preg)) {
				if(attr.startsWith("/")) {
					attr=host+attr.substring(1);
				}
				if(attr.startsWith("./")) {			
					attr=path+attr.substring(2);
				}
				if(!attr.startsWith("http")) {
					attr=path+attr;
				}	
				Elements select = next.select("img");	
				if(select.size()>0) {
					Element first = select.first();
					String src = first.attr("src");
					if(src.startsWith("/")) {
						src=host+src.substring(1);
					}
					if(src.startsWith("./")) {			
						src=path+src.substring(2);
					}
					if(!src.startsWith("http")) {
						src=path+src;
					}	
					aimg.put(attr, src);
				}
				if(used.contains(attr)) {
					continue;
				}
				stack.push(attr);
				i++;
			}			
		}
		if(i==0) {
			return "指定页面中未找到相关链接";
		}
		return "";
	}
	
	protected static String getFileName(String file){
		int index=file.indexOf("?");
		index=index>0?index:file.indexOf("#");
		if(index==-1) {
			file=file.substring(file.lastIndexOf("/")+1);
		}else {
			file = file.substring(0, index);
			file=file.substring(file.lastIndexOf("/")+1);
		}
		return file;
	}
	
	protected static void layer(String content){
		logger.info(content);
    	JSONObject object=new JSONObject();
    	object.put("type", "layer");
    	object.put("content", content);   
    	try {
			Broadcast.echo((int)Userinfo.get("aid"), object.toString());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	protected static void success(String content){
		logger.info(content);
    	JSONObject object=new JSONObject();
    	object.put("type", "alert");
    	object.put("content", content);
    	object.put("style", "alert-success");
    	object.put("title", "提示");
    	object.put("position", "topRight");
    	object.put("autoClose", true);
    	try {
			Broadcast.echo((int)Userinfo.get("aid"), object.toString());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
    
	protected static void error(String content){
		logger.info(content);
    	JSONObject object=new JSONObject();
    	object.put("type", "alert");
    	object.put("content", content);
    	object.put("style", "alert-danger");
    	object.put("title", "提示");
    	object.put("position", "topRight");
    	object.put("autoClose", true);
    	try {
			Broadcast.echo((int)Userinfo.get("aid"), object.toString());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}